perm filename ALCODE.POX[HAL,HE]2 blob
sn#196330 filedate 1976-01-15 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00016 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00003 00002 \|\\M0BASL30[HAL,HE]\
C00006 00003
C00008 00004 \⊂'210104\←=40\ε\ Set for single spacing, everypage
C00009 00005 \!sec(Introduction)
C00012 00006 \!sec(Input format)
C00016 00007 \!sec(Predeclared variables and constants)
C00018 00008 \!sec(Declarations)
C00021 00009 \!sec(Global Declarations)
C00027 00010 \!sec(Control Statements)
C00033 00011 \!sec(Device control statements)
C00039 00012 \!sec(Graph Structure Statements)
C00045 00013 \!sec(Miscellaneous statements)
C00047 00014 \!sec(Statements that emit no code.)
C00053 00015 \!sec(Expressions)
C00059 00016 \!sec(How to make your very own AL program.)
C00069 ENDMK
C⊗;
\|\\M0BASL30[HAL,HE];\;
\M1BASI30[HAL,HE];\;
\M2BASB30;\;
\M4GRK30;\;
\M5LPT;\;
\M6BDR40;\;
\M7BDR66;\;
\←R\-L\/=10;\→W\;
\←R\→r\←L\→l\;
\⊂'404444;\; God only knows what all this does.
\8tb(i)<\←W\*=⊗i⊗;\+L\→.>\;
\8sec(t)<\C\F6⊗t⊗\F0>\; any text arg
\8subsec(t)[\F2⊗t⊗\F0]\; any text arg
\8indent(lm)<\←⊗lm⊗\+W\→⊗lm⊗\→.>\; q-reg name (single char)
\8outdent(lm)<\←⊗lm⊗\-W\→⊗lm⊗>\; q-reg name (single char)
\8narrow(lm,rm)<\←⊗lm⊗\+W\→⊗lm⊗\→.\←⊗rm⊗\-W\→⊗rm⊗>\;
\8widen(lm,rm)<\←⊗lm⊗\-W\→⊗lm⊗\→.\←⊗rm⊗\+W\→⊗rm⊗>\;
\∞beginexample[\Ql\QL\ql\!narrow(L,R);\←=0;\λ]\;
\∞endexample[\!widen(L,R);\←=0;\λ\ql]\;
\←=0;\λ\;
\∞cd[\↑=10;.\⊗]\;
\∞egtb[\!tb(1);]\;
\;NEXT BIT STOLEN FROM DATIME.POX[1,REM] & MODIFIED TO TASTE
\8MONTH(NSTR)[\!MONTH⊗NSTR⊗;]\;
\∞MONTH1[JAN]\;
\∞MONTH2[FEB]\;
\∞MONTH3[MAR]\;
\∞MONTH4[APR]\;
\∞MONTH5[MAY]\;
\∞MONTH6[JUN]\;
\∞MONTH7[JUL]\;
\∞MONTH8[AUG]\;
\∞MONTH9[SEP]\;
\∞MONTH10[OCT]\;
\∞MONTH11[NOV]\;
\∞MONTH12[DEC]\;
\∞DAY0⊂Sunday⊃\∞DAY1⊂Monday⊃\∞DAY2⊂Tuesday⊃\∞DAY3⊂Wednesday⊃\;
\∞DAY4⊂Thursday⊃\∞DAY5⊂Friday⊃\∞DAY6⊂Saturday⊃\;
\∞DATE[\QY\QD\u'400101;\L=-18;\→D\
\←D\%=31;\+=1;\P\←D\/=31;\→D\%=12;\+=1;\P\←D\/=12;\+=1964;\→Y\
\qD\!MONTH(\DD);\qD \←D\/=10;\D∀\←D\%=10;\D∀, \
\DY\qD\qY]\;
\,
\C\F6Interim
\C\F7AL User's Handbook\F2
\C\F2Russell H. Taylor
\CStanford Artificial Intelligence Laboratory
\C\!DATE;
\!beginexample;
\F6I.\!egtb;Introduction
II.\!egtb;Input Format
III.\!egtb;Predeclared Variables and Constants
IV.\!egtb;Declarations
V.\!egtb;Global Declarations
VI.\!egtb;Control Structures
VII.\!egtb;Device Control Statements
VIII.\!egtb;Graph Structure Statements
IX.\!egtb;Miscellaneous Statements
X.\!egtb;Statements that Emit No Code
XI.\!egtb;Expressions
XII.\!egtb;Operating Instructions
\!endexample;
\⊂'210104;\←=40;\ε\; Set for single spacing, everypage
\←=1;\→N\
\oHEAD{2[\DN]}\ Put page number on bottom of first page.
\←R\→D\1HEAD;\¬D\→D\2HEAD;\¬D\-=1;\→D\ D is the X coordinate of the page number
\WHEAD,D=2050;\
\←N\+=1;\→N\;
\∞EVERYPAGE[\
\oHEAD{2[\DN]}\
\←R\→D\1HEAD;\¬D\→D\2HEAD;\¬D\-=1;\→D\
\WHEAD,D=150;\
\←N\+=1;\→N]\;
\,
\!sec(Introduction);
\JThis document is intended to serve as an "interim programmer's
manual" for people who may want to use AL in its present state.
To get your own copy, XSPOOL ALCODE.XGP[HAL,HE].
Since a full-blown parser for AL programs has yet to be implemented,
an input syntax somewhat resembling LISP s-expressions has been
supplied as an interim measure. The basic elements in this syntax
are atomic symbols and forms like:\.
\!beginexample;
(<keyword> <e1> <e2> ... <ek> )
\!endexample;
\Jwhich correspond in a more or less one-to-one manner with the record
structures used inside the compiler. For instance, the program\.
\!beginexample;
BEGIN
FRAME a,b;ROTN r;TRANS t;
r←ROT(YHAT,180*DEG);
a ← FRAME(r,VECTOR(0,0,2));
MOVE YELLOW TO FRAME(r,VECTOR(1,0,2));
b ← FRAME(r,VECTOR(0,0,3));
AFFIX a TO YELLOW BY t RIGIDLY;
MOVE a TO b;
MOVE a TO b*TRANS(ROT(XHAT,90*DEG),VECTOR(1,1,1));
UNFIX a FROM YELLOW;
MOVE YELLOW TO YPARK;
END;
\!endexample;
would be written as
\!beginexample;
(PR
(BL (FVAR a b)(RVAR r)(TVAR t)
(AS r (RMAKE YHAT (SSMUL 180 DEG)))
(AS a (FMAKE r (VMAKE 0 0 2)))
(MO YARM (FMAKE r (VMAKE 1 0 2)))
(AS b (FMAKE r (VMAKE 0 0 3)))
(AFFIX a YARM t () RIGIDLY)
(MO a b)
(MO a (TTMUL b (TMAKE (AXW_ROTN XHAT (SSMUL 90 DEG))(VMAKE 1 1 1))))
(UNFIX a YARM)
(MO YARM YPARK)
)
)
\!endexample;
\JGenerally speaking, the semantics of the various language constructs have
remained pretty much the same as given in AIM-243, \F1AL, A Programming
System for Automation\F0, and familiarity with that document is assumed.
However, there are some differences, as is to be expected with an evolving
system, and many of the features of AL do not yet have any corresponding
"s-expression"; as implementation proceeds, these will be added.\.
\!sec(Input format);
\!subsec(Atomic Symbols);
Examples:\!egtb;"This is a string."
\!egtb;ident
\!egtb;3.14159
\JAtomic symbols include identifiers (discussed below), real numbers,
string constants, and certain special characters (such as "≠").\.
\!subsec(Identifiers);
Examples:\!egtb;x
\!egtb;ABC102
\!egtb;a_very_long_identifier
\JIdentifiers
are used as variables, labels, keywords, and names for certain predeclared
constants.
Identifiers consist of a letter followed by any string of letters and digits,
For this purpose the special character "_" is treated like a letter.
All letters are coerced to upper case on input; thus, "foo", "FOO" and "Foo" are
all the same identifier. This manual will use upper case letters to indicate
"reserved" identifiers, and lower case to indicate everything else.
In general, a non-reserved identifier must be declared (either in
a variable declaration or by using it as a label) before being used in
a program. However, if an undefined identifier is used in a context where
a variable is expected,
the system will make an implicit declaration for it and print a message to
the user. For instance,\.
\!beginexample;
(AS y 10)
\!endexample;
\Jwould print out "Y declared a scalar variable". However, this facility
should be viewed as a bug recovery mechanism and not as the preferred
way to declare variables. No promisses are made that such declarations will
always work correctly. WARNING: Attempts to redefine reserved identifiers
(keywords, predeclared variables, and predeclared constants) will not
work correctly.
\.
\!subsec(Structure forms);
Syntax:\!egtb;(<keyword> <element1> ... <element n>)
\!egtb;(<label> <keyword> <element 1> ... <element n>)
Examples:\!egtb;(SVAR x y z)
\!egtb;(foo ON e1 (AS x 1))
\JThe two forms are equivalent, except that <label>, if it appears,
may be used subsequently to refer to the semantic entity defined by
the form. <label> must have been previously declared as a "label"
variable of the appropriate kind.\.
\!sec(Predeclared variables and constants);
\!subsec(Variables);
\JYARM, BARM -- Frame variables corresponding to the location
of the YELLOW and BLUE arms (actually, the location and orientation
of a coordinate system tacked onto the end of the YELLOW and
BLUE hands, respectively). Used as device names for MOVE statements.
YHAND, BHAND -- Scalar variables giving the opening of the YELLOW
and BLUE fingers. Used as device names for "operate" statements.
OLDV, NEWV -- Hold the old and new values for a variable when a "changer"
is invoked. Actually, these might be better referred to as "variable-like"
entities, since their type, etc., depend on what "changer" they appear in.
AFFIXED -- Atom used in AFFIXED pattern
RIGIDLY, NONRIGIDLY -- Atoms that appear in AFFIXED patterns and which
are used to specify kind of affixment in an AFFIX statement.\.
\!subsec(Constants);
\!beginexample;
PI = 3.141592653
DEG = PI/180
XHAT = VECTOR(1,0,0)
YHAT = VECTOR(0,1,0)
ZHAT = VECTOR(0,0,1)
NILVECT = VECTOR(0,0,0)
NILROTN = ROT(ZHAT,0)
NILTRANS = TRANS(NILROTN,NILVECT)
STATION = FRAME(NILROTN,NILVECT)
YPARK = parking place for YELLOW arm
BPARK = parking place for BLUE arm
\!endexample;
\!sec(Declarations);
Syntax:\!egtb;(<declarator> <id1> <id2> ... <idn>)
Example:\!egtb;(SVAR x y z)
\JCauses variables <id1>, ..., <idn> to be declared with the
type specified by <declarator> as local variables to the
current block. Declarations may appear anywhere a statement
is legal (although some places -- such as the body of
an "on monitor" -- don't make a lot of sense.) In particular,
statements and declarations may be intermixed within
a block. However, a declaration only affects those statements that come
after it within the block. Thus,
if a variable is used within a block
before its declaration appears, then its next "higher" declaration
will be used. For instance:\.
\!beginexample;
(BL (SVAR x y)
(BL (AS x 3)
(SVAR x)
(AS x 4)
)
(AS y x)
)
\!endexample;
\Jwill set variable "y" to 3.
Legal <declarator>s are:\.
\!beginexample;
SVAR -- Scalar variable
VVAR -- Vector variable
RVAR -- Rotation variable
TVAR -- Trans variable
FVAR -- Frame variable
ATOM -- Atom variable
EVAR -- Event variable
WVAR -- World name
ONLAB -- Condition monitor label
CLCLAB -- Calculator label
CHGLAB -- Changer label
STMLAB -- Statement label
\!endexample;
\JNOTE: Internally, AL associates a unique print name with every variable
by tacking the block name on in front of the variable name. Block names
are generated from an internal block numbering and have the form "$$B1",
"$$B2", etc. Thus, our little example above would have three scalar variables
$$B1.X, $$B1.Y, and $$B2.X. When a program is printed out, the internal
names for the variables are given. \.
\!sec(Global Declarations);
Syntax:\!egtb;(GVAR <declaration 1> <declaration 2> ... <declaration n>)
Example:\!egtb;(GVAR (TVAR t1 t2) (FVAR a b) )
\JGlobal variables are provided to facilitate chaining together several
short AL programs to produce longer sequences. Normally, whenever
a block is exited, all variables local to that block are destroyed,
as are any graph structure affixments that depend on them. This means
that once your program has run, all traces of its effects would be
lost from the runtime environment (except, of course, for the
final position of the arms and other similar "real world" changes").
Global variables, on the other hand, are kept on a separate list
(the "global variable store") which is "owned" by the runtime
system, and are never deallocated. However, a given global may
only be referenced from inside a block in which it is declared.
For instance, in\.
\!beginexample;
(BL (FVAR a)
(BL (GVAR (FVAR b))
(AS a b) (COMMENT ok)
)
(AS a b) (COMMENT illegal)
)
\!endexample;
\Jthe first assignment statement is legal, but the second is not.
The first time a global variable is accessed from within a block
where it is declared, the global
variable store is searched for a variable with the same print
name as that given in the global declaration. (Note: this is
one case where the variable's declared id, rather than its
unique internal id is used. Thus, in our example, "b" is searched
for.) If the variable is not found, then storage for the
variable is allocated, and the appropriate entries are made in
the store. In any event, a pointer to the variable is returned
and put away where the block can find it. Subsequent attempts to
access the variable will be able to use this pointer, so that
the store does not have to be searched repeatedly for the same variable.
Execution for the
block proceeds normally, except that on block exit the
pointer to the variable is merely dropped, and nothing is done
to the variable itself.
WARNING: In the present implementation, NO TYPE CHECKING is done
when linking up global variables. This means that you can lose in
a big way if you have a global variable declared as, say, a TVAR in
one place, and an SVAR in another.
As already mentioned, one principal use for global variables is
facilitating communication between separately compiled AL programs.
Typical examples of this would be chaining together several short
programs to get around memory limitations (which are currently rather
severe) or interfacing between several semi-autonomous functions,
such as a pick-and-place module and assembly modules for two different
sorts of part. Another eventual use will be provision of a communication
mechanism with external programs (e.g., vision modules)
which need to fetch or store variable values. These programs may be
living on either the PDP-11 or on the PDP-10.
NOTE: Presently, compiler and runtime facilities for supporting
global variables are not completely debugged. Furthermore, the
runtime system facilities for chaining together several programs
aren't fully implemented. This means that global variables really aren't
too useful quite yet, although their appearance within a program won't
cause it to blow up (as far as we know). Beat on your local AL hackers
to get this finished.\.
\!sec(Control Statements);
\!subsec(Block);
Syntax:\!egtb;(BL <statement 1> <statement 2> ... <statement n>)
Example:\!egtb;(BL (SVAR x) (AS x 2) (SVAR y) (AS x y) )
\JCorresponds to the classical ALGOL block/compound statement. As
mentioned before, declarations may be interspersed freely with
executable statements, but only affect those statements in the
block that occur after the declaration.\.
\!subsec(Coblock);
Syntax:\!egtb;(CO <statement 1> <statement 2> ... <statement n> )
Example:\!egtb;(CO (MO YARM YPARK) (MO BARM BPARK) )
\JCorresponds to the AL "COBEGIN ... COEND" construct. The statements
are executed concurrently, and the coblock does not terminate until
all the constituent statements terminate. Note that a coblock is
NOT a block. Although it is legal for one of the statements to
be a declaration, the local variables so declared will be added to
the block in which the coblock appears.\.
\!subsec(Conditional statement);
Syntax:\!egtb;(IF <condition> <"then" statement> <"else" statement> )
Example:\!egtb;(IF (SLE x 4) (MO YARM a) (MO BARM a))
\!egtb;(IF (SEQ x 5) (MO BARM BPARK))
\JCorresponds to the classical "IF ... THEN ... ELSE". Note that the
<"else" statement> may be omitted. Currently the <condition> expressions
allowed are:\.
\!beginexample;
(SLT e1 e2) -- e1 < e2
(SLE e1 e2) -- e1 ≤ e2
(SEQ e1 e2) -- e1 = e2
(SNE e1 e2) -- e1 ≠ e2
(SGE e1 e2) -- e1 ≥ e2
(SGT e1 e2) -- e1 > e2
\!endexample;
where e1 and e2 are scalar-valued expressions. Soon to be added:
\!beginexample;
(EQL e1 e2)
(NEQ e1 e2)
\!endexample;
\Jwhere e1 and e2 may be any arithmetic type (so long as they have the
same type). Also:\.
\!beginexample;
(AND <condition 1> <condition 2>)
(OR <condition 1> <condition 2>)
(NOT <condition>)
\!endexample;
\!subsec(Compile-time conditionals);
Syntax:\!egtb;(CIF <condition> <"then" statement> <"else" statement> )
Example:\!egtb;(CIF (SLE (NOMV x) 4) (MO YARM a) (MO BARM a))
\JCorresponds to the "PLAN IF" construct in AL. Just like regular
conditional statement except that the <condition> must be constant
and that only code for the "true" part will be emitted.
NOTE: This may go away, in which case the compiler will automatically
detect constant conditions and take appropriate actions.\.
\!subsec(Loop statements);
Syntax:\!egtb;(WH <condition> <statement>)
\!egtb;(FO <scalar variable> <initial value> <step value> <final value> <statement>)
Example:\!egtb;(WH (SLT x 3) (BL (MO a b) (AS x (SADD x 1)) )
\!egtb;(FO x 1 1 10 (MO a (FMAKE NILROT (VMAKE x x x))) )
These correspond to the usual ALGOL-like WHILE and FOR loops.
\!subsec(Condition monitors);
Syntax:\!egtb;(ON <condition> <statement> )
Example:\!egtb;(ON (SGT t 3) (MO BARM b) )
\JCorresponds to the AL "ON <condition> DO <statement>". The <condition>
must have the form of a simple comparison involving scalars, etc., or
else must be an event variable.
Check with your friendly local AL hackers about all this.\.
\!subsec(Program);
Syntax:\!egtb;(PR <statement> )
Example:\!egtb;(PR (BL (MO YARM YPARK) (MO BARM BPARK) ))
\JThis "statement" is provided for the convenience of the AL compiler.
All you have to know about it is to put (PR ... ) around any AL
program you wish to have compiled. In other words, the "top level"
of any s-expression you wish AL to compile must be a program. Presently,
that is the only place this form should appear.\.
\!sec(Device control statements);
\;page modified 1/15/76 by RF
\!subsec(Move statement);
Syntax:\!egtb;(MO <frame variable> <dest expr> <clause 1> ... <clause n>)
Examples:\!egtb;(MO YARM a)
\!egtb;(MO BARM (TTMUL BPARK t))
\!egtb;(MO a b (VIA (TTMUL a t1)) (VIA c) (ON e3 (EV e4 +)) )
\JThis construct defines a single-manipulator motion statement. Here,
the <frame variable> must be controllable in the environment of
the motion statement, and the <dest expression> must evaluate to
either a frame or trans. (In the latter case, AL assumes that
STATION*<dest expr> is meant.) A frame variable is controllable
if it is one of the arm frames (YARM and BARM) or if it is affixed
to a controllable frame. For instance, after a sequence like\.
\!beginexample;
(FVAR a b c d e f)
(TVAR t1 t2 t3 t4 t5)
(AFFIX a YARM t1 () NONRIGIDLY )
(AFFIX a b t2 () RIGIDLY)
(AFFIX c d t3 () RIGIDLY)
(AFFIX d e t4 () NONRIGIDLY)
(AFFIX d BARM t5 () RIGIDLY)
\!endexample;
\Jframes a, b, c, d, YARM, and BARM will all be controllable, while
e and f will not. In cases where the <frame> is not one of the arms,
the compiler uses its planning model of the affixment structure
to determine which arm is to be moved and modifies the <destination
expression> to produce the correct effect. For instance, \.
\!beginexample;
(MO a YPARK)
\!endexample;
is treated like
\!beginexample;
(MO YARM (TTMUL YPARK (TINVRT t1)) )
\!endexample;
\JIf the controllable "frame" is YHAND or BHAND or affixed to such
a scalar, then the resulting motion will only involve the hand.
However, the planning model will not understand this construct.
Currently, the only <clause> types recognized by the compiler are\.
\!beginexample;
(VIA <dest expr> )
(ON <condition> <statement>)
(DURATION <op> <scalar expression>)
\!endexample;
\JThe VIA clauses define intermediate locations through which the motion must
pass. The order of the clauses determines the order of motion through the points.
The ON clause is just like an ON statement, and is recognized correctly.
The condition monitor so defined will only be enabled during the motion statement.
This clause is, however, not yet treated correctly by the code generator
or runtime system.
The DURATION clause is used to constrain the time taken for the motion.
The <op> must be "<", ">", or "=". This clause may also be inserted
within a VIA clause, in which case it constrains the segment of the
motion that ends with that VIA point.
Other clause types (e.g., for FORCE or TORQUE) will be added
as these features are put up in the runtime system.\.
\!subsec(Center statement);
Syntax:\!egtb;(CENTER <arm variable> <clause 1> ... <clause n>)
Examples:\!egtb;(CENTER YARM)
\!egtb;(CENTER BARM (ON e3 (EV e4 +)))
\JThis construct defines a single-manipulator center statement. Here,
the <arm variable> must be either YARM or BARM.
The specified arm will accomodate to whatever is between the fingers
as they close. The only allowed clause is ON, and it is not
treated properly yet.\.
\!subsec(Stop);
Syntax:\!egtb;(STOP <mechanism variable>)
Examples:\!egtb;(STOP YARM)
\!egtb;(STOP BHAND)
\JThe <mechanism variable> must be an arm (YARM, BARM) or a hand (YHAND,
BHAND). Any motion underway with that device is terminated
cleanly.
\.
\!sec(Graph Structure Statements);
\!subsec(Affix Statement);
Syntax:\!egtb;(AFFIX <frame var 1> <frame var 2> <by var> <at expr> <rigidity>)
Examples:\!egtb;(AFFIX f1 f2 t () RIGIDLY)
\!egtb;(AFFIX f1 f2 t (TMAKE NILROTN XHAT) NONRIGIDLY)
\JSpecifies affixment of <frame var 1> to <frame var 2> by the specified
<by var> (which must be a TRANS variable) at an offset specified by
<at expr>. If <rigidity> is RIGIDLY then the affixment is assumed
to be symmetric, so that modifying one of the frame variables
will cause the other one to be modified, too. If <rigidity> is
NONRIGIDLY, then an asymmetric affixment is made, in which
changing the second frame changes the first, but changing the first
causes the <by var> to be modified. If <at expr> is left null, as
in our first example, then a default of inv(f2)*f1 is assumed.
The graph structure modifications produced by our first example
are thus:\.
\!beginexample;
(CLCLAB g001 g002)
(AS t (TTMUL (TINVRT f2) f1) )
(GAS f1 = (g001 CLC (TTMUL f2 t)) )
(GAS f2 = (g001 CLC (TTMUL f1 (TINVRT t))) )
\!endexample;
and those for our second example are:
\!beginexample;
(CLCLAB g003) (CHGLAB g004)
(AS t (TMAKE NILROTN XHAT) )
(GAS f1 = (g003 CLC (TTMUL f2 t)) )
(ALSO_DO f1 (goo4 CHG (AS t NEWV)) )
\!endexample;
\Jwhere g001, g002, g003, and g004 are names invented by the compiler.
NOTE: If the two frame variables are already (directly) affixed,
then the previous affixment will be undone. This is to avoid inconsistencies.
However, chains of affixments are not checked for, and may get you into
trouble.\.
\!subsec(Unfix Statement);
Syntax:\!egtb;(UNFIX <frame var 1> <frame var 2> )
Example:\!egtb;(UNFIX f1 f2)
\JThis statement causes the current affixment between f1 and f2 to be undone.
If f1 and f2 are not currently affixed, the statement has no effect.\.
\!subsec(Explicit graph structure modification);
\JThese primitives allow explicit modification to the graph structure
associated with a variable. This can be a rather risky thing to do,
and users are urged to use the affixment statements given earlier
wherever practical.\.
\!subsec(Calculator assignment);
Syntax:\!egtb;(GAS <var> <op> <calculator> )
Examples:\!egtb;(GAS f = (c1 CLC (TTMUL a b)) )
\!egtb;(GAS f ≠ c1 )
\Jchanges the calculator list for variable <var>.
The available values for <op> are "=", for "is computed by", "≠" for "is no
longer computed by", and "<" for "is only computed by". <calculator> may
be either the name of an old calculator or a new calculator expression, given by\.
\!beginexample;
(<label> CLC <expression> )
\!endexample;
\Jwhich associates the <expression> with the name <label>.
If <op> is "≠", then
the <calculator> better be the name of some calculator previously used
in a calculator assignment for <var>. (Ugh! what a sentence!).\.
\!subsec(When-changing statement);
Syntax:\!egtb;(<also_op> <var> <changer> )
Examples:\!egtb;(ALSO_DO x (cx CHG AS y x)) )
\!egtb;(ALSO_DONT x cx)
\JLike calculator assignment, this statement makes modifications to the
graph structure for variable <var>. Available values for <also_op>
are "ALSO_DO", which says to perform the indicated <changer> whenever
<var> is changed, "ALSO_DONT", which undoes a particular ALSO_DO,
and "ALSO_ONLY", which undoes all previous ALSO_DOs and then does an
ALSO_DO on its argument. <changer> may be either the name of a previous
change action, or else may be a new action, specified by \.
\!beginexample;
(<label> CHG <statement> )
\!endexample;
\JThe special tokens OLDV and NEWV may be used to refer to the old and
new values of <var>.\.
\!sec(Miscellaneous statements);
\!subsec(Assignment statement);
Syntax:\!egtb;(AS <var> <expression> )
Example:\!egtb;(AS t1 (TTMUL t2 t3))
\JComputes the value of <expression> and stores it away in <var>. Any
graph nodes that depend on <var> will be invalidated, and any
"changers" for <var> will be called. If <var> is of type <frame>
and <expression> produces a trans, then STATION*<expression> is
assumed.\.
\!subsec(Event signal and wait);
Syntax:\!egtb;(EV <event var> <op> )
Examples:\!egtb;(EV e1 + )
\!egtb;(EV e2 - )
\JThe "+" form says to signal the event specified by <event var>, and
"-" says to wait for the event specified by <event var>.\.
\!sec(Statements that emit no code.);
\!subsec(Source file requests);
Syntax:\!egtb;(DSKIN <fileid>)
Example:\!egtb;(DSKIN "P5.AL[HAL,RHT]")
\Jcauses the specified file to be opened for reading. One "s-expression"
is then read from the file and substituted for the DSKIN statement.
You are STRONGLY urged only to use this construct from the very
top level of AL (I.e., where input from the TTY is being requested).
Otherwise, you will become very confused. Please note that the specified
file remains open for input after the program has been read in. This
means that several AL programs may be placed in one file. Presumably,
the compiler will then do the "right" thing, although it may wind
up overwriting all but the last program read in (Complain to RF about this).
Also, note that if the file contains less than a whole program (Typically,
because you have forgotten some right parentheses), AL reverts to input
from the TTY (prompting you with another "*").\.
\!subsec(Comments);
Syntax:\!egtb;(COMMENT <anything> )
Example:\!egtb;(COMMENT this is a comment )
\JThe entire construct is treated like a null statement. Note that
this is not quite the same thing as being ignored entirely. For
instance,\.
\!beginexample;
(IF (SGT x 2)
(COMMENT You think this will be ignored)
(AS x 2)
(AS x 1)
)
\!endexample;
won't do what you probably mean it to. Sorry.
\!subsec(Arithmetic assertions);
Syntax:\!egtb;(ASSERT (AF <var> <reln> <value> ) <worldid> )
Example:\!egtb;(ASSERT (AF YARM = YPARK) )
\JCurrently, the only allowed <reln> is "=", which is used for planning
value assignment. <worldid> is used to specify a particular planning "world".
If it is left blank, then the current world will be used. (Usually,
this is what you want). Planning values may be retrieved by use of
the (NOMV <var>) construct. (NOTE: "AF" is mnemonic for "arithmetic fact").\.
\!subsec(Symbolic assertions);
Syntax:\!egtb;(ASSERT (SF <token 1> <token 2> ... <token n> ) <worldid> )
Examples:\!egtb;(ASSERT (SF gripper_device vise1 ))
\!egtb;(ASSERT (SF DEPROACH f1 (TMAKE NILROTN ZHAT)))
\JUsed to add symbolic assertions to the AL compiler's database.
Again, the current "world" is assumed as a default for <worldid>.
(NOTE: "SF" is mnemonic for "symbolic fact".)\.
\!subsec(Denials);
Syntax:\!egtb;(DENY (AF <var> = <value> ) <worldid> )
\!egtb;(DENY (SF <token 1> ... <token n>) <worldid>)
Example:\!egtb;(DENY (SF DEPROACH f1 (TMAKE NILROTN ZHAT)))
Used to remove facts from the planning model for world <worldid>.
\!subsec(World declaration);
Syntax:\!egtb;(NW <worldid>)
Example:\!egtb;(NW australia)
Sets the current planning "world" to be <worldid>.
\!subsec(Debugging requests);
Syntax:\!egtb;(PVL (<var 1> <var 2> ... <var n>) <worldid> )
\!egtb;(DBD <worldid> )
Examples:\!egtb;(PVL (x y a b YARM ) )
\!egtb;(DBD australia)
\JCurrently, these statements are useful primarily in debugging the
simulator. PVL ("print value list")
causes the simulator to print out it's current
model of the graph structure for the named variables in the specified
planning world.
DBD ("data base dump") causes the all facts in that are "true" in
the named planning world to be printed out.
As usual, if <worldid> is ommitted for either statement,
then the current world is assumed.
Eventually, there will doubtless be similar statements to direct
the runtime system to print things out. Again, see your local
represenative.\.
\!sec(Expressions);
Syntax:\!egtb;(<op> <arg1> <arg2> ... <argn>)
Example:\!egtb;(SADD 1 2)
\JPresently, all arithmetic operations take one, two, or three arguments,
depending on the operation.
(i.e., things like (SADD 1 2 3 4) don't work. ). Values for <op> are indicated below.
NOTATION: "s" means "scalar", "v" means "vector", "r" means "rotation",
"t" means "trans", and "f" means frame. Also a frame may be used as an
argument anywhere a trans may be used.
"*" indicates that the operation
isn't yet available in the runtime system. "**" indicates that it isn't
available in the compiler. It is expected that these restrictions
will disappear soon.\.
Scalar-valued expressions:
\!egtb;(SADD s1 s2) \!tb(5);; s1+s2
\!egtb;(SSUB s1 s2) \!tb(5);; s1-s2
\!egtb;(SMUL s1 s2) \!tb(5);; s1*s2
\!egtb;(SNEG s1 ) \!tb(5);; -s1
\!egtb;(SDIV s1 s2) \!tb(5);; s1/s2
**\!egtb;(SABS s) \!tb(5);; |s|
**\!egtb;(STOS s1 s2) \!tb(5);; s1↑s2
\!egtb;(VMAGN v) \!tb(5);; |v|
\!egtb;(VDOT v1 v2) \!tb(5);; v1 \!cd; v2
**\!egtb;(ANGLE v1 v2) \!tb(5);; arccos(uvect(v1) \!cd; uvect(v2))
**\!egtb;(RMAGN r) \!tb(5);; (positive) rotation angle of r (see note)
Vector-valued expressions:
\!egtb;(VMAKE s1 s2 s2) \!tb(5);; VECTOR(s1,s2,s3)
\!egtb;(SVMUL s1 v1) \!tb(5);; scales a vector
\!egtb;(VADD v1 v2) \!tb(5);; v1+v2
**\!egtb;(VSUB v1 v2) \!tb(5);; v1-v2
*\!egtb;(RVMUL r v2) \!tb(5);; r*v
\!egtb;(TVMUL t v) \!tb(5);; t*v
**\!egtb;(VCROSS v1 v2) \!tb(5);; cross product of v1 & v2
**\!egtb;(UVECT v) \!tb(5);; v/magn(v)
**\!egtb;(AXIS r) \!tb(5);; rotation axis of r (see note)
**\!egtb;(POS t) \!tb(5);; position part of a trans
Rotation-valued expressions:
*\!egtb;(AXW_ROTN v s) \!tb(5);; right-handed rotation of s radians about v
**\!egtb;(ORIENT t) \!tb(5);; rotation part of t
**\!egtb;(VTOV v1 v2) \!tb(5);; rotation that takes uvect(v1) into uvect(v2)
**\!egtb;(RRMUL r1 r2) \!tb(5);; r1*r2
**\!egtb;(RINV r) \!tb(5);; inverse(r)
**\!egtb;(VVROT v1 v2) \!tb(5);; rotates ZHAT into uvect(v2) and v1 into v1-v2 plane
Trans-valued expressions:
*\!egtb;(TMAKE r v) \!tb(5);; TRANS(r,v)
* \!egtb;(FTOF f1 f2) \!tb(5);; inv(f2)*f1 -- may go away. do not use.
*\!egtb;(TVADD t v) \!tb(5);; TRANS(rotpart(t),v+tranlspart(v))
*\!egtb;(TINVRT t) \!tb(5);; inverse(t)
\!egtb;(TTMUL t1 t2) \!tb(5);; t1*t2
**\!egtb;(VVVTRANS v1 v2 v3)\!tb(5);; TRANS(VVROT(v2-v1,v3-v1),v1)
Frame-valued expressions:
\!egtb;(FMAKE r v) \!tb(5);; FRAME(r,v)
\JNote: ROT(AXIS(r),MAGN(r)) = r. AXIS(r) and MAGN(r) are extracted assuming
a right-handed rotation (between 0 and π radians) about the axis.\.
\!sec(How to make your very own AL program.);
Don't do any of this without first informing RF or RHT.
\!subsec(To make the compiler);
\JThe latest version, when there is one, is AL.DMP[H,RF]. Use it if it
exists. If not, here is the fastest way to load it:\.
\!beginexample;
.AL H,RF \!tb(5);;alias to RF
.R LOADER 50 \!tb(5);;this way it does not wait for COREGET
*/Y/VAL,TCALC<alt>\!tb(5);;load RAID, you see.
.SAV AL \!tb(5);;or save it somewhere else if you prefer
.AL \!tb(5);;alias back
\!endexample;
\!subsec(To run the compiler);
\JThis program is a read-parse-stinterp-codegenerate loop. It begins
by asking OUTPUT TO TTY? and OUTPUT TO FILE? I usually answer Y and
N. It then responds with *. Input an s-expression, and as soon as
you end a line with a balanced parenthesis, it is compiled. The
interpreted s-expression is printed out (on whatever output device
you specified) and after code has been generated, another * appears.
Note that one legal s-expression is\.
\!beginexample;
(DSKIN "AL.DAT")
\!endexample;
\Jthis will read the file AL.DAT and take input from there. You ought
to look at this file; it will give you an idea of what the
s-expressions look like. Code is generated in the four files
COMP.ALn with n=0,1,2,3. Once you have finished generating the code
you want, exit the read loop by this unappetizing method:\.
\!beginexample;
*↑C
.F \!tb(5);;close the output files
. \!tb(5);;do wait for this dot, to make sure all is well.
\!endexample;
\!subsec(To assemble the COMP.ALn files.);
\JYou have to run PALX across the files. There is a file
COMP.PAL[HAL,HE] which is just what you want. Glance at it first to
make sure that REALSW is set to 1, so the right files get assembled.
Then:\.
\!beginexample;
.AL HAL,HE\!tb(5);;alias to HE
.R PALX \!tb(5);;invoke the assmebler
FOO←COMP\!tb(5);;this will make a copy called FOO.BIN
<some palx output>
*↑C
.
\!endexample;
\!subsec(To run the system);
\JTo get the latest system, if it exists, you try the following:\.
\!beginexample;
.A ELF \!tb(5);;so no one will ruin your core image
.R 11TTY\!tb(5);;the 11 loading program
\C<some initial garbage. Now watch out, 11tty uses character input>
*Get save file = HAL\!tb(5);;Just type the G and watch the screen.
\!tb(5);;if the file is not found, do this instead:
*Load bin file = HAL
\!tb(5);;if that is not found, see below
*Overlay bin file = K1[11,SYS
*Overlay bin file = FOO\!tb(5);;the one you just made
*Start at 130000\!tb(5);;gets you to DDT on the VT05 console
\C<now you have to move to the VT05. You are in DDT>
*1000<alt><alt>G\!tb(5);;you are off and running.
\!endexample;
\!subsec(To assemble the system);
\JIf HAL.BIN and HAL.SAV are not available or not desired, you can make
a new runtime by assembling HAL.PAL[HAL,HE]. Look on page two to see
which switches are turned on. You most likely want to load INTERP,
but not ALAID and not the arm stuff, unless you know it is working.
\.